Revert "Removed tons of api that we dont absolutely need in GtkCellAreaContext:"
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Fri, 26 Nov 2010 04:23:01 +0000 (13:23 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Fri, 26 Nov 2010 12:37:51 +0000 (21:37 +0900)
This reverts commit 5f7787ab2ead2cdd11ebe17b16dd9498daaaf9c5.

gtk/gtkcellareabox.c
gtk/gtkcellareaboxcontext.c
gtk/gtkcellareaboxcontext.h
gtk/gtkcellareacontext.c
gtk/gtkcellareacontext.h

index 8950c53c0fb6e693b9ffce53fc277bbbe9bfb1d2..02ec53f9e37ff1cf32e21f1004b6a988704809ec 100644 (file)
@@ -1284,7 +1284,8 @@ compute_size (GtkCellAreaBox        *box,
   for (i = 0; i < priv->groups->len; i++)
     {
       CellGroup *group = &g_array_index (priv->groups, CellGroup, i);
-      gint       group_min = 0, group_nat = 0;
+      gint       group_min_size = 0;
+      gint       group_nat_size = 0;
 
       for (list = group->cells; list; list = list->next)
        {
@@ -1304,33 +1305,42 @@ compute_size (GtkCellAreaBox        *box,
                  min_size += priv->spacing;
                  nat_size += priv->spacing;
                }
-
-             if (group_min > 0)
+             
+             if (group_min_size > 0)
                {
-                 group_min += priv->spacing;
-                 group_nat += priv->spacing;
+                 group_min_size += priv->spacing;
+                 group_nat_size += priv->spacing;
                }
-
-             min_size  += renderer_min_size;
-             nat_size  += renderer_nat_size;
-             group_min += renderer_min_size;
-             group_nat += renderer_nat_size;
+             
+             min_size       += renderer_min_size;
+             nat_size       += renderer_nat_size;
+             group_min_size += renderer_min_size;
+             group_nat_size += renderer_nat_size;
            }
          else
            {
-             min_size  = MAX (min_size, renderer_min_size);
-             nat_size  = MAX (nat_size, renderer_nat_size);
-             group_min = MAX (group_min, renderer_min_size);
-             group_nat = MAX (group_nat, renderer_nat_size);
+             min_size       = MAX (min_size, renderer_min_size);
+             nat_size       = MAX (nat_size, renderer_nat_size);
+             group_min_size = MAX (group_min_size, renderer_min_size);
+             group_nat_size = MAX (group_nat_size, renderer_nat_size);
            }
        }
 
-      if (for_size < 0)
+      if (orientation == GTK_ORIENTATION_HORIZONTAL)
+       {
+         if (for_size < 0)
+           gtk_cell_area_box_context_push_group_width (context, group->id, group_min_size, group_nat_size);
+         else
+           gtk_cell_area_box_context_push_group_width_for_height (context, group->id, for_size,
+                                                                  group_min_size, group_nat_size);
+       }
+      else
        {
-         if (orientation == GTK_ORIENTATION_HORIZONTAL)
-           gtk_cell_area_box_context_push_group_width (context, group->id, group_min, group_nat);
+         if (for_size < 0)
+           gtk_cell_area_box_context_push_group_height (context, group->id, group_min_size, group_nat_size);
          else
-           gtk_cell_area_box_context_push_group_height (context, group->id, group_min, group_nat);
+           gtk_cell_area_box_context_push_group_height_for_width (context, group->id, for_size,
+                                                                  group_min_size, group_nat_size);
        }
     }
 
@@ -1519,6 +1529,17 @@ compute_size_for_opposing_orientation (GtkCellAreaBox        *box,
 
       min_size = MAX (min_size, group_min);
       nat_size = MAX (nat_size, group_nat);
+
+      if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+       {
+         gtk_cell_area_box_context_push_group_height_for_width (context, group_idx, for_size,
+                                                                group_min, group_nat);
+       }
+      else
+       {
+         gtk_cell_area_box_context_push_group_width_for_height (context, group_idx, for_size,
+                                                                group_min, group_nat);
+       }
     }
 
   *minimum_size = min_size;
index 6ba773c0eef8c4a9e3268e5a8aaa3d406ca2617b..caf23df0712dacf382ef99844a4c71b389ddc604 100644 (file)
@@ -32,15 +32,31 @@ static void      gtk_cell_area_box_context_finalize                         (GOb
 
 /* GtkCellAreaContextClass */
 static void      gtk_cell_area_box_context_flush_preferred_width            (GtkCellAreaContext *context);
+static void      gtk_cell_area_box_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
+                                                                            gint                width);
 static void      gtk_cell_area_box_context_flush_preferred_height           (GtkCellAreaContext *context);
+static void      gtk_cell_area_box_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
+                                                                            gint                height);
 static void      gtk_cell_area_box_context_flush_allocation                 (GtkCellAreaContext *context);
 static void      gtk_cell_area_box_context_sum_preferred_width              (GtkCellAreaContext *context);
+static void      gtk_cell_area_box_context_sum_preferred_height_for_width   (GtkCellAreaContext *context,
+                                                                            gint                width);
 static void      gtk_cell_area_box_context_sum_preferred_height             (GtkCellAreaContext *context);
+static void      gtk_cell_area_box_context_sum_preferred_width_for_height   (GtkCellAreaContext *context,
+                                                                            gint                height);
 static void      gtk_cell_area_box_context_allocate_width                   (GtkCellAreaContext *context,
                                                                             gint                width);
 static void      gtk_cell_area_box_context_allocate_height                  (GtkCellAreaContext *context,
                                                                             gint                height);
 
+static void      free_cache_array                                           (GArray          *array);
+
+/* CachedSize management */
+typedef struct {
+  gint     min_size;
+  gint     nat_size;
+} CachedSize;
+
 typedef struct {
   gint     min_size;
   gint     nat_size;
@@ -53,6 +69,10 @@ struct _GtkCellAreaBoxContextPrivate
   GArray *base_widths;
   GArray *base_heights;
 
+  /* Table of per height/width hash tables of per renderer CachedSizes */
+  GHashTable *widths;
+  GHashTable *heights;
+
   /* Allocation info for this context if any */
   gint                      alloc_width;
   gint                      alloc_height;
@@ -62,6 +82,12 @@ struct _GtkCellAreaBoxContextPrivate
 
 G_DEFINE_TYPE (GtkCellAreaBoxContext, gtk_cell_area_box_context, GTK_TYPE_CELL_AREA_CONTEXT);
 
+static void
+free_cache_array (GArray *array)
+{
+  g_array_free (array, TRUE);
+}
+
 static void
 gtk_cell_area_box_context_init (GtkCellAreaBoxContext *box_context)
 {
@@ -75,6 +101,11 @@ gtk_cell_area_box_context_init (GtkCellAreaBoxContext *box_context)
   priv->base_widths  = g_array_new (FALSE, TRUE, sizeof (BaseSize));
   priv->base_heights = g_array_new (FALSE, TRUE, sizeof (BaseSize));
 
+  priv->widths       = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                             NULL, (GDestroyNotify)free_cache_array);
+  priv->heights      = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                             NULL, (GDestroyNotify)free_cache_array);
+
   priv->alloc_width  = 0;
   priv->alloc_height = 0;
   priv->orientation_allocs   = NULL;
@@ -91,11 +122,15 @@ gtk_cell_area_box_context_class_init (GtkCellAreaBoxContextClass *class)
   object_class->finalize = gtk_cell_area_box_context_finalize;
 
   context_class->flush_preferred_width            = gtk_cell_area_box_context_flush_preferred_width;
+  context_class->flush_preferred_height_for_width = gtk_cell_area_box_context_flush_preferred_height_for_width;
   context_class->flush_preferred_height           = gtk_cell_area_box_context_flush_preferred_height;
+  context_class->flush_preferred_width_for_height = gtk_cell_area_box_context_flush_preferred_width_for_height;
   context_class->flush_allocation                 = gtk_cell_area_box_context_flush_allocation;
 
   context_class->sum_preferred_width            = gtk_cell_area_box_context_sum_preferred_width;
+  context_class->sum_preferred_height_for_width = gtk_cell_area_box_context_sum_preferred_height_for_width;
   context_class->sum_preferred_height           = gtk_cell_area_box_context_sum_preferred_height;
+  context_class->sum_preferred_width_for_height = gtk_cell_area_box_context_sum_preferred_width_for_height;
 
   context_class->allocate_width  = gtk_cell_area_box_context_allocate_width;
   context_class->allocate_height = gtk_cell_area_box_context_allocate_height;
@@ -114,6 +149,8 @@ gtk_cell_area_box_context_finalize (GObject *object)
 
   g_array_free (priv->base_widths, TRUE);
   g_array_free (priv->base_heights, TRUE);
+  g_hash_table_destroy (priv->widths);
+  g_hash_table_destroy (priv->heights);
 
   g_free (priv->orientation_allocs);
 
@@ -142,6 +179,23 @@ gtk_cell_area_box_context_flush_preferred_width (GtkCellAreaContext *context)
     (gtk_cell_area_box_context_parent_class)->flush_preferred_width (context);
 }
 
+static void
+gtk_cell_area_box_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
+                                                           gint                width)
+{
+  GtkCellAreaBoxContext        *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+  GtkCellAreaBoxContextPrivate *priv        = box_context->priv;
+
+  /* Flush all sizes for special -1 value */
+  if (width < 0)
+    g_hash_table_remove_all (priv->heights);
+  else
+    g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
+
+  GTK_CELL_AREA_CONTEXT_CLASS
+    (gtk_cell_area_box_context_parent_class)->flush_preferred_height_for_width (context, width);
+}
+
 static void
 gtk_cell_area_box_context_flush_preferred_height (GtkCellAreaContext *context)
 {
@@ -161,6 +215,23 @@ gtk_cell_area_box_context_flush_preferred_height (GtkCellAreaContext *context)
     (gtk_cell_area_box_context_parent_class)->flush_preferred_height (context);
 }
 
+static void
+gtk_cell_area_box_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
+                                                           gint                height)
+{
+  GtkCellAreaBoxContext        *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+  GtkCellAreaBoxContextPrivate *priv        = box_context->priv;
+
+  /* Flush all sizes for special -1 value */
+  if (height < 0)
+    g_hash_table_remove_all (priv->widths);
+  else
+    g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
+
+  GTK_CELL_AREA_CONTEXT_CLASS
+    (gtk_cell_area_box_context_parent_class)->flush_preferred_width_for_height (context, height);
+}
+
 static void
 gtk_cell_area_box_context_flush_allocation (GtkCellAreaContext *context)
 {
@@ -214,6 +285,55 @@ gtk_cell_area_box_context_sum_preferred_width (GtkCellAreaContext *context)
   gtk_cell_area_context_push_preferred_width (context, min_size, nat_size);
 }
 
+static void
+gtk_cell_area_box_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
+                                                         gint                width)
+{
+  GtkCellAreaBoxContext        *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+  GtkCellAreaBoxContextPrivate *priv        = box_context->priv;
+  GArray                    *group_array;
+  GtkCellArea               *area;
+  GtkOrientation             orientation;
+  gint                       spacing, i;
+  gint                       min_size = 0, nat_size = 0;
+
+  group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (width));
+
+  if (group_array)
+    {
+      area        = gtk_cell_area_context_get_area (context);
+      spacing     = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+      orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+      
+      for (i = 0; i < group_array->len; i++)
+       {
+         CachedSize *size = &g_array_index (group_array, CachedSize, i);
+         
+         if (orientation == GTK_ORIENTATION_VERTICAL)
+           {
+             /* Dont add spacing for 0 size groups, they can be 0 size because
+              * they contain only invisible cells for this round of requests 
+              */
+             if (min_size > 0 && size->nat_size > 0)
+               {
+                 min_size += spacing;
+                 nat_size += spacing;
+               }
+             
+             min_size += size->min_size;
+             nat_size += size->nat_size;
+           }
+         else
+           {
+             min_size = MAX (min_size, size->min_size);
+             nat_size = MAX (nat_size, size->nat_size);
+           }
+       }
+
+      gtk_cell_area_context_push_preferred_height_for_width (context, width, min_size, nat_size);
+    }
+}
+
 static void
 gtk_cell_area_box_context_sum_preferred_height (GtkCellAreaContext *context)
 {
@@ -256,6 +376,55 @@ gtk_cell_area_box_context_sum_preferred_height (GtkCellAreaContext *context)
   gtk_cell_area_context_push_preferred_height (context, min_size, nat_size);
 }
 
+static void
+gtk_cell_area_box_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
+                                                         gint                height)
+{
+  GtkCellAreaBoxContext        *box_context = GTK_CELL_AREA_BOX_CONTEXT (context);
+  GtkCellAreaBoxContextPrivate *priv        = box_context->priv;
+  GArray                    *group_array;
+  GtkCellArea               *area;
+  GtkOrientation             orientation;
+  gint                       spacing, i;
+  gint                       min_size = 0, nat_size = 0;
+
+  group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (height));
+
+  if (group_array)
+    {
+      area        = gtk_cell_area_context_get_area (context);
+      spacing     = gtk_cell_area_box_get_spacing (GTK_CELL_AREA_BOX (area));
+      orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (area));
+      
+      for (i = 0; i < group_array->len; i++)
+       {
+         CachedSize *size = &g_array_index (group_array, CachedSize, i);
+         
+         if (orientation == GTK_ORIENTATION_HORIZONTAL)
+           {
+             /* Dont add spacing for 0 size groups, they can be 0 size because
+              * they contain only invisible cells for this round of requests 
+              */
+             if (min_size > 0 && size->nat_size > 0)
+               {
+                 min_size += spacing;
+                 nat_size += spacing;
+               }
+             
+             min_size += size->min_size;
+             nat_size += size->nat_size;
+           }
+         else
+           {
+             min_size = MAX (min_size, size->min_size);
+             nat_size = MAX (nat_size, size->nat_size);
+           }
+       }
+
+      gtk_cell_area_context_push_preferred_width_for_height (context, height, min_size, nat_size);
+    }
+}
+
 static GtkRequestedSize *
 gtk_cell_area_box_context_get_requests (GtkCellAreaBoxContext *box_context,
                                        GtkOrientation         orientation,
@@ -489,6 +658,36 @@ gtk_cell_area_box_context_push_group_width (GtkCellAreaBoxContext *box_context,
   size->nat_size = MAX (size->nat_size, natural_width);
 }
 
+void
+gtk_cell_area_box_context_push_group_height_for_width  (GtkCellAreaBoxContext *box_context,
+                                                       gint                   group_idx,
+                                                       gint                   for_width,
+                                                       gint                   minimum_height,
+                                                       gint                   natural_height)
+{
+  GtkCellAreaBoxContextPrivate *priv;
+  GArray                       *group_array;
+  CachedSize                   *size;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+  priv = box_context->priv;
+  g_return_if_fail (group_idx < priv->base_widths->len);
+
+  group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+  if (!group_array)
+    {
+      group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+      g_array_set_size (group_array, priv->base_heights->len);
+
+      g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), group_array);
+    }
+
+  size = &g_array_index (group_array, CachedSize, group_idx);
+  size->min_size = MAX (size->min_size, minimum_height);
+  size->nat_size = MAX (size->nat_size, natural_height);
+}
+
 void
 gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
                                             gint                   group_idx,
@@ -508,6 +707,36 @@ gtk_cell_area_box_context_push_group_height (GtkCellAreaBoxContext *box_context,
   size->nat_size = MAX (size->nat_size, natural_height);
 }
 
+void
+gtk_cell_area_box_context_push_group_width_for_height (GtkCellAreaBoxContext *box_context,
+                                                      gint                   group_idx,
+                                                      gint                   for_height,
+                                                      gint                   minimum_width,
+                                                      gint                   natural_width)
+{
+  GtkCellAreaBoxContextPrivate *priv;
+  GArray                    *group_array;
+  CachedSize                *size;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+  priv        = box_context->priv;
+  g_return_if_fail (group_idx < priv->base_widths->len);
+
+  group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+  if (!group_array)
+    {
+      group_array = g_array_new (FALSE, TRUE, sizeof (CachedSize));
+      g_array_set_size (group_array, priv->base_heights->len);
+
+      g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), group_array);
+    }
+
+  size = &g_array_index (group_array, CachedSize, group_idx);
+  size->min_size = MAX (size->min_size, minimum_width);
+  size->nat_size = MAX (size->nat_size, natural_width);
+}
+
 void
 gtk_cell_area_box_context_get_group_width (GtkCellAreaBoxContext *box_context,
                                           gint                   group_idx,
@@ -531,6 +760,43 @@ gtk_cell_area_box_context_get_group_width (GtkCellAreaBoxContext *box_context,
     *natural_width = size->nat_size;
 }
 
+void
+gtk_cell_area_box_context_get_group_height_for_width (GtkCellAreaBoxContext *box_context,
+                                                     gint                   group_idx,
+                                                     gint                   for_width,
+                                                     gint                  *minimum_height,
+                                                     gint                  *natural_height)
+{
+  GtkCellAreaBoxContextPrivate *priv;
+  GArray                    *group_array;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+  priv        = box_context->priv;
+  g_return_if_fail (group_idx < priv->base_widths->len);
+
+  group_array = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+
+  if (group_array)
+    {
+      CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
+
+      if (minimum_height)
+       *minimum_height = size->min_size;
+
+      if (natural_height)
+       *natural_height = size->nat_size;
+    }
+  else
+    {
+      if (minimum_height)
+       *minimum_height = -1;
+
+      if (natural_height)
+       *natural_height = -1;      
+    }
+}
+
 void
 gtk_cell_area_box_context_get_group_height (GtkCellAreaBoxContext *box_context,
                                            gint                   group_idx,
@@ -554,6 +820,43 @@ gtk_cell_area_box_context_get_group_height (GtkCellAreaBoxContext *box_context,
     *natural_height = size->nat_size;
 }
 
+void
+gtk_cell_area_box_context_get_group_width_for_height (GtkCellAreaBoxContext *box_context,
+                                                     gint                   group_idx,
+                                                     gint                   for_height,
+                                                     gint                  *minimum_width,
+                                                     gint                  *natural_width)
+{
+  GtkCellAreaBoxContextPrivate *priv;
+  GArray                       *group_array;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_BOX_CONTEXT (box_context));
+
+  priv = box_context->priv;
+  g_return_if_fail (group_idx < priv->base_widths->len);
+
+  group_array = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+
+  if (group_array)
+    {
+      CachedSize *size = &g_array_index (group_array, CachedSize, group_idx);
+
+      if (minimum_width)
+       *minimum_width = size->min_size;
+
+      if (natural_width)
+       *natural_width = size->nat_size;
+    }
+  else
+    {
+      if (minimum_width)
+       *minimum_width = -1;
+
+      if (natural_width)
+       *natural_width = -1;      
+    }
+}
+
 GtkRequestedSize *
 gtk_cell_area_box_context_get_widths (GtkCellAreaBoxContext *box_context,
                                      gint                  *n_widths)
index 29d9f80a7abe1d540e0991b795eaf5ec3313bed6..01f7dc6cba6d15bc1dc40ae9d3380572d9e84f04 100644 (file)
@@ -72,20 +72,47 @@ void    gtk_cell_area_box_context_push_group_width             (GtkCellAreaBoxCo
                                                                gint                   group_idx,
                                                                gint                   minimum_width,
                                                                gint                   natural_width);
+
+void    gtk_cell_area_box_context_push_group_height_for_width  (GtkCellAreaBoxContext *box_context,
+                                                               gint                   group_idx,
+                                                               gint                   for_width,
+                                                               gint                   minimum_height,
+                                                               gint                   natural_height);
+
 void    gtk_cell_area_box_context_push_group_height            (GtkCellAreaBoxContext *box_context,
                                                                gint                   group_idx,
                                                                gint                   minimum_height,
                                                                gint                   natural_height);
 
+void    gtk_cell_area_box_context_push_group_width_for_height  (GtkCellAreaBoxContext *box_context,
+                                                               gint                   group_idx,
+                                                               gint                   for_height,
+                                                               gint                   minimum_width,
+                                                               gint                   natural_width);
+
 /* Fetch cell-group sizes */
 void    gtk_cell_area_box_context_get_group_width              (GtkCellAreaBoxContext *box_context,
                                                                gint                   group_idx,
                                                                gint                  *minimum_width,
                                                                gint                  *natural_width);
+
+void    gtk_cell_area_box_context_get_group_height_for_width   (GtkCellAreaBoxContext *box_context,
+                                                               gint                   group_idx,
+                                                               gint                   for_width,
+                                                               gint                  *minimum_height,
+                                                               gint                  *natural_height);
+
 void    gtk_cell_area_box_context_get_group_height             (GtkCellAreaBoxContext *box_context,
                                                                gint                   group_idx,
                                                                gint                  *minimum_height,
                                                                gint                  *natural_height);
+
+void    gtk_cell_area_box_context_get_group_width_for_height   (GtkCellAreaBoxContext *box_context,
+                                                               gint                   group_idx,
+                                                               gint                   for_height,
+                                                               gint                  *minimum_width,
+                                                               gint                  *natural_width);
+
 GtkRequestedSize *gtk_cell_area_box_context_get_widths         (GtkCellAreaBoxContext *box_context,
                                                                gint                  *n_widths);
 GtkRequestedSize *gtk_cell_area_box_context_get_heights        (GtkCellAreaBoxContext *box_context,
index 1d0598f793b1aff35de2eae47020a54389f3b9d7..61646708dba1ab4cda76af401869a571e7ade8cc 100644 (file)
@@ -28,6 +28,7 @@
 #include "gtkprivate.h"
 
 /* GObjectClass */
+static void      gtk_cell_area_context_finalize                       (GObject            *object);
 static void      gtk_cell_area_context_dispose                        (GObject            *object);
 static void      gtk_cell_area_context_get_property                   (GObject            *object,
                                                                       guint               prop_id,
@@ -40,13 +41,26 @@ static void      gtk_cell_area_context_set_property                   (GObject
 
 /* GtkCellAreaContextClass */
 static void      gtk_cell_area_context_real_flush_preferred_width            (GtkCellAreaContext *context);
+static void      gtk_cell_area_context_real_flush_preferred_height_for_width (GtkCellAreaContext *context,
+                                                                             gint                width);
 static void      gtk_cell_area_context_real_flush_preferred_height           (GtkCellAreaContext *context);
+static void      gtk_cell_area_context_real_flush_preferred_width_for_height (GtkCellAreaContext *context,
+                                                                             gint                height);
 static void      gtk_cell_area_context_real_flush_allocation                 (GtkCellAreaContext *context);
 static void      gtk_cell_area_context_real_allocate_width                   (GtkCellAreaContext *context,
                                                                              gint                width);
 static void      gtk_cell_area_context_real_allocate_height                  (GtkCellAreaContext *context,
                                                                              gint                height);
 
+/* CachedSize management */
+typedef struct {
+  gint min_size;
+  gint nat_size;
+} CachedSize;
+
+static CachedSize *cached_size_new  (gint min_size, gint nat_size);
+static void        cached_size_free (CachedSize *size);
+
 struct _GtkCellAreaContextPrivate
 {
   GtkCellArea *cell_area;
@@ -57,6 +71,9 @@ struct _GtkCellAreaContextPrivate
   gint         nat_height;
   gint         alloc_width;
   gint         alloc_height;
+
+  GHashTable  *widths;
+  GHashTable  *heights;
 };
 
 enum {
@@ -68,6 +85,14 @@ enum {
   PROP_NAT_HEIGHT
 };
 
+enum {
+  SIGNAL_WIDTH_CHANGED,
+  SIGNAL_HEIGHT_CHANGED,
+  LAST_SIGNAL
+};
+
+static guint cell_area_context_signals[LAST_SIGNAL] = { 0 };
+
 G_DEFINE_TYPE (GtkCellAreaContext, gtk_cell_area_context, G_TYPE_OBJECT);
 
 static void
@@ -84,6 +109,10 @@ gtk_cell_area_context_init (GtkCellAreaContext *context)
   priv->nat_width  = -1;
   priv->min_height = -1;
   priv->nat_height = -1;
+  priv->widths     = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                           NULL, (GDestroyNotify)cached_size_free);
+  priv->heights    = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+                                           NULL, (GDestroyNotify)cached_size_free);
 }
 
 static void 
@@ -92,21 +121,46 @@ gtk_cell_area_context_class_init (GtkCellAreaContextClass *class)
   GObjectClass     *object_class = G_OBJECT_CLASS (class);
 
   /* GObjectClass */
+  object_class->finalize     = gtk_cell_area_context_finalize;
   object_class->dispose      = gtk_cell_area_context_dispose;
   object_class->get_property = gtk_cell_area_context_get_property;
   object_class->set_property = gtk_cell_area_context_set_property;
 
   /* GtkCellAreaContextClass */
   class->flush_preferred_width            = gtk_cell_area_context_real_flush_preferred_width;
+  class->flush_preferred_height_for_width = gtk_cell_area_context_real_flush_preferred_height_for_width;
   class->flush_preferred_height           = gtk_cell_area_context_real_flush_preferred_height;
+  class->flush_preferred_width_for_height = gtk_cell_area_context_real_flush_preferred_width_for_height;
   class->flush_allocation                 = gtk_cell_area_context_real_flush_allocation;
 
-  class->sum_preferred_width   = NULL;
-  class->sum_preferred_height  = NULL;
+  class->sum_preferred_width            = NULL;
+  class->sum_preferred_height_for_width = NULL;
+  class->sum_preferred_height           = NULL;
+  class->sum_preferred_width_for_height = NULL;
 
   class->allocate_width  = gtk_cell_area_context_real_allocate_width;
   class->allocate_height = gtk_cell_area_context_real_allocate_height;
 
+  cell_area_context_signals[SIGNAL_HEIGHT_CHANGED] =
+    g_signal_new (I_("height-changed"),
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0, /* Class offset (just a notification, no class handler) */
+                 NULL, NULL,
+                 _gtk_marshal_VOID__INT_INT_INT,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
+
+  cell_area_context_signals[SIGNAL_WIDTH_CHANGED] =
+    g_signal_new (I_("width-changed"),
+                 G_TYPE_FROM_CLASS (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0, /* Class offset (just a notification, no class handler) */
+                 NULL, NULL,
+                 _gtk_marshal_VOID__INT_INT_INT,
+                 G_TYPE_NONE, 3,
+                 G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
+
   g_object_class_install_property (object_class,
                                    PROP_CELL_AREA,
                                    g_param_spec_object ("area",
@@ -158,9 +212,44 @@ gtk_cell_area_context_class_init (GtkCellAreaContextClass *class)
   g_type_class_add_private (object_class, sizeof (GtkCellAreaContextPrivate));
 }
 
+
+
+/*************************************************************
+ *                      Cached Sizes                         *
+ *************************************************************/
+static CachedSize *
+cached_size_new (gint min_size, 
+                gint nat_size)
+{
+  CachedSize *size = g_slice_new (CachedSize);
+
+  size->min_size = min_size;
+  size->nat_size = nat_size;
+
+  return size;
+}
+
+static void
+cached_size_free (CachedSize *size)
+{
+  g_slice_free (CachedSize, size);
+}
+
 /*************************************************************
  *                      GObjectClass                         *
  *************************************************************/
+static void
+gtk_cell_area_context_finalize (GObject *object)
+{
+  GtkCellAreaContext        *context = GTK_CELL_AREA_CONTEXT (object);
+  GtkCellAreaContextPrivate *priv = context->priv;
+
+  g_hash_table_destroy (priv->widths);
+  g_hash_table_destroy (priv->heights);
+
+  G_OBJECT_CLASS (gtk_cell_area_context_parent_class)->finalize (object);
+}
+
 static void
 gtk_cell_area_context_dispose (GObject *object)
 {
@@ -246,6 +335,40 @@ gtk_cell_area_context_real_flush_preferred_width (GtkCellAreaContext *context)
   g_object_thaw_notify (G_OBJECT (context));
 }
 
+static void
+notify_invalid_height (gpointer            width_ptr,
+                      CachedSize         *size,
+                      GtkCellAreaContext *context)
+{
+  gint width = GPOINTER_TO_INT (width_ptr);
+
+  /* Notify size invalidated */
+  g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], 
+                0, width, -1, -1);
+}
+
+static void
+gtk_cell_area_context_real_flush_preferred_height_for_width (GtkCellAreaContext *context,
+                                                            gint                width)
+{
+  GtkCellAreaContextPrivate *priv = context->priv;
+
+  /* Flush all sizes for special -1 value */
+  if (width < 0)
+    {
+      g_hash_table_foreach (priv->heights, (GHFunc)notify_invalid_height, context);
+      g_hash_table_remove_all (priv->heights);
+    }
+  else
+    {
+      g_hash_table_remove (priv->heights, GINT_TO_POINTER (width));
+
+      /* Notify size invalidated */
+      g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], 
+                    0, width, -1, -1);
+    }
+}
+
 static void
 gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context)
 {
@@ -260,6 +383,40 @@ gtk_cell_area_context_real_flush_preferred_height (GtkCellAreaContext *context)
   g_object_thaw_notify (G_OBJECT (context));
 }
 
+static void
+notify_invalid_width (gpointer            height_ptr,
+                     CachedSize         *size,
+                     GtkCellAreaContext *context)
+{
+  gint height = GPOINTER_TO_INT (height_ptr);
+
+  /* Notify size invalidated */
+  g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], 
+                0, height, -1, -1);
+}
+
+static void
+gtk_cell_area_context_real_flush_preferred_width_for_height (GtkCellAreaContext *context,
+                                                            gint                height)
+{
+  GtkCellAreaContextPrivate *priv = context->priv;
+
+  /* Flush all sizes for special -1 value */
+  if (height < 0)
+    {
+      g_hash_table_foreach (priv->widths, (GHFunc)notify_invalid_width, context);
+      g_hash_table_remove_all (priv->widths);
+    }
+  else
+    {
+      g_hash_table_remove (priv->widths, GINT_TO_POINTER (height));
+
+      /* Notify size invalidated */
+      g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], 
+                    0, height, -1, -1);
+    }
+}
+
 static void
 gtk_cell_area_context_real_flush_allocation (GtkCellAreaContext *context)
 {
@@ -309,7 +466,9 @@ gtk_cell_area_context_flush (GtkCellAreaContext *context)
   g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
 
   gtk_cell_area_context_flush_preferred_width (context);
+  gtk_cell_area_context_flush_preferred_height_for_width (context, -1);
   gtk_cell_area_context_flush_preferred_height (context);
+  gtk_cell_area_context_flush_preferred_width_for_height (context, -1);
   gtk_cell_area_context_flush_allocation (context);
 }
 
@@ -321,6 +480,15 @@ gtk_cell_area_context_flush_preferred_width (GtkCellAreaContext *context)
   GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_width (context);
 }
 
+void
+gtk_cell_area_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
+                                                       gint                for_width)
+{
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_height_for_width (context, for_width);
+}
+
 void
 gtk_cell_area_context_flush_preferred_height (GtkCellAreaContext *context)
 {
@@ -329,6 +497,15 @@ gtk_cell_area_context_flush_preferred_height (GtkCellAreaContext *context)
   GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_height (context);
 }
 
+void
+gtk_cell_area_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
+                                                       gint                for_height)
+{
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  GTK_CELL_AREA_CONTEXT_GET_CLASS (context)->flush_preferred_width_for_height (context, for_height);
+}
+
 void
 gtk_cell_area_context_flush_allocation (GtkCellAreaContext *context)
 {
@@ -350,6 +527,20 @@ gtk_cell_area_context_sum_preferred_width (GtkCellAreaContext *context)
     class->sum_preferred_width (context);
 }
 
+void
+gtk_cell_area_context_sum_preferred_height_for_width (GtkCellAreaContext *context,
+                                                     gint                for_width)
+{
+  GtkCellAreaContextClass *class;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context);
+
+  if (class->sum_preferred_height_for_width)
+    class->sum_preferred_height_for_width (context, for_width);
+}
+
 void
 gtk_cell_area_context_sum_preferred_height (GtkCellAreaContext *context)
 {
@@ -363,6 +554,20 @@ gtk_cell_area_context_sum_preferred_height (GtkCellAreaContext *context)
     class->sum_preferred_height (context);
 }
 
+void
+gtk_cell_area_context_sum_preferred_width_for_height (GtkCellAreaContext *context,
+                                                     gint                for_height)
+{
+  GtkCellAreaContextClass *class;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  class = GTK_CELL_AREA_CONTEXT_GET_CLASS (context);
+
+  if (class->sum_preferred_width_for_height)
+    class->sum_preferred_width_for_height (context, for_height);
+}
+
 void
 gtk_cell_area_context_allocate_width (GtkCellAreaContext *context,
                                      gint                width)
@@ -407,6 +612,39 @@ gtk_cell_area_context_get_preferred_width (GtkCellAreaContext *context,
     *natural_width = priv->nat_width;
 }
 
+void
+gtk_cell_area_context_get_preferred_height_for_width (GtkCellAreaContext *context,
+                                                     gint                for_width,
+                                                     gint               *minimum_height,
+                                                     gint               *natural_height)
+{
+  GtkCellAreaContextPrivate *priv;
+  CachedSize                *size;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  priv = context->priv;
+
+  size = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+
+  if (size)
+    {
+      if (minimum_height)
+       *minimum_height = size->min_size;
+
+      if (natural_height)
+       *natural_height = size->nat_size;
+    }
+  else
+    {
+      if (minimum_height)
+       *minimum_height = -1;
+
+      if (natural_height)
+       *natural_height = -1;
+    }
+}
+
 void
 gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
                                            gint               *minimum_height,
@@ -425,6 +663,39 @@ gtk_cell_area_context_get_preferred_height (GtkCellAreaContext *context,
     *natural_height = priv->nat_height;
 }
 
+void
+gtk_cell_area_context_get_preferred_width_for_height (GtkCellAreaContext *context,
+                                                     gint                for_height,
+                                                     gint               *minimum_width,
+                                                     gint               *natural_width)
+{
+  GtkCellAreaContextPrivate *priv;
+  CachedSize                *size;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  priv = context->priv;
+
+  size = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+
+  if (size)
+    {
+      if (minimum_width)
+       *minimum_width = size->min_size;
+
+      if (natural_width)
+       *natural_width = size->nat_size;
+    }
+  else
+    {
+      if (minimum_width)
+       *minimum_width = -1;
+
+      if (natural_width)
+       *natural_width = -1;
+    }
+}
+
 void
 gtk_cell_area_context_get_allocation (GtkCellAreaContext *context,
                                      gint               *width,
@@ -473,6 +744,50 @@ gtk_cell_area_context_push_preferred_width (GtkCellAreaContext *context,
   g_object_thaw_notify (G_OBJECT (context));
 }
 
+void
+gtk_cell_area_context_push_preferred_height_for_width (GtkCellAreaContext *context,
+                                                      gint                for_width,
+                                                      gint                minimum_height,
+                                                      gint                natural_height)
+{
+  GtkCellAreaContextPrivate *priv;
+  CachedSize             *size;
+  gboolean                changed = FALSE;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  priv = context->priv;
+
+  size = g_hash_table_lookup (priv->heights, GINT_TO_POINTER (for_width));
+
+  if (!size)
+    {
+      size = cached_size_new (minimum_height, natural_height);
+
+      g_hash_table_insert (priv->heights, GINT_TO_POINTER (for_width), size);
+
+      changed = TRUE;
+    }
+  else
+    {
+      if (minimum_height > size->min_size)
+       {
+         size->min_size = minimum_height;
+         changed = TRUE;
+       }
+
+      if (natural_height > size->nat_size)
+       {
+         size->nat_size = natural_height;
+         changed = TRUE;
+       }
+    }
+  
+  if (changed)
+    g_signal_emit (context, cell_area_context_signals[SIGNAL_HEIGHT_CHANGED], 0, 
+                  for_width, size->min_size, size->nat_size);
+}
+
 void
 gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
                                             gint                minimum_height,
@@ -502,3 +817,47 @@ gtk_cell_area_context_push_preferred_height (GtkCellAreaContext *context,
 
   g_object_thaw_notify (G_OBJECT (context));
 }
+
+void
+gtk_cell_area_context_push_preferred_width_for_height (GtkCellAreaContext *context,
+                                                      gint                for_height,
+                                                      gint                minimum_width,
+                                                      gint                natural_width)
+{
+  GtkCellAreaContextPrivate *priv;
+  CachedSize             *size;
+  gboolean                changed = FALSE;
+
+  g_return_if_fail (GTK_IS_CELL_AREA_CONTEXT (context));
+
+  priv = context->priv;
+
+  size = g_hash_table_lookup (priv->widths, GINT_TO_POINTER (for_height));
+
+  if (!size)
+    {
+      size = cached_size_new (minimum_width, natural_width);
+
+      g_hash_table_insert (priv->widths, GINT_TO_POINTER (for_height), size);
+
+      changed = TRUE;
+    }
+  else
+    {
+      if (minimum_width > size->min_size)
+       {
+         size->min_size = minimum_width;
+         changed = TRUE;
+       }
+
+      if (natural_width > size->nat_size)
+       {
+         size->nat_size = natural_width;
+         changed = TRUE;
+       }
+    }
+  
+  if (changed)
+    g_signal_emit (context, cell_area_context_signals[SIGNAL_WIDTH_CHANGED], 0, 
+                  for_height, size->min_size, size->nat_size);
+}
index 0782f7836489cfeb1d09a0203207ee48ba40af2a..8e3621f313266bf318089b74b28cbd7b5d8b53de 100644 (file)
@@ -55,14 +55,22 @@ struct _GtkCellAreaContextClass
 
   /* Subclasses can use this to flush their alignments/allocations */
   void    (* flush_preferred_width)              (GtkCellAreaContext *context);
+  void    (* flush_preferred_height_for_width)   (GtkCellAreaContext *context,
+                                                 gint                width);
   void    (* flush_preferred_height)             (GtkCellAreaContext *context);
+  void    (* flush_preferred_width_for_height)   (GtkCellAreaContext *context,
+                                                 gint                height);
   void    (* flush_allocation)                   (GtkCellAreaContext *context);
 
   /* These must be invoked after a series of requests before consulting 
    * the context values, implementors use this to push the overall
    * requests while acconting for any internal alignments */
   void    (* sum_preferred_width)                (GtkCellAreaContext *context);
+  void    (* sum_preferred_height_for_width)     (GtkCellAreaContext *context,
+                                                 gint                width);
   void    (* sum_preferred_height)               (GtkCellAreaContext *context);
+  void    (* sum_preferred_width_for_height)     (GtkCellAreaContext *context,
+                                                 gint                height);
 
   /* Store an allocation value for a GtkCellArea contextual to a range of
    * treemodel rows */
@@ -85,13 +93,21 @@ GtkCellArea *gtk_cell_area_context_get_area                         (GtkCellArea
 /* Apis for GtkCellArea clients to flush the cache */
 void         gtk_cell_area_context_flush                            (GtkCellAreaContext *context);
 void         gtk_cell_area_context_flush_preferred_width            (GtkCellAreaContext *context);
+void         gtk_cell_area_context_flush_preferred_height_for_width (GtkCellAreaContext *context,
+                                                                    gint                for_width);
 void         gtk_cell_area_context_flush_preferred_height           (GtkCellAreaContext *context);
+void         gtk_cell_area_context_flush_preferred_width_for_height (GtkCellAreaContext *context,
+                                                                    gint                for_height);
 void         gtk_cell_area_context_flush_allocation                 (GtkCellAreaContext *context);
 
 /* Apis for GtkCellArea clients to sum up the results of a series of requests, this
  * call is required to reduce the processing while calculating the size of each row */
 void         gtk_cell_area_context_sum_preferred_width              (GtkCellAreaContext *context);
+void         gtk_cell_area_context_sum_preferred_height_for_width   (GtkCellAreaContext *context,
+                                                                    gint                for_width);
 void         gtk_cell_area_context_sum_preferred_height             (GtkCellAreaContext *context);
+void         gtk_cell_area_context_sum_preferred_width_for_height   (GtkCellAreaContext *context,
+                                                                    gint                for_height);
 
 /* Apis to set an allocation size in one dimension or another, the subclass specific context
  * will store allocated positions/sizes for individual cells or groups of cells */
@@ -104,9 +120,17 @@ void         gtk_cell_area_context_allocate_height                  (GtkCellArea
 void         gtk_cell_area_context_get_preferred_width              (GtkCellAreaContext *context,
                                                                     gint               *minimum_width,
                                                                     gint               *natural_width);
+void         gtk_cell_area_context_get_preferred_height_for_width   (GtkCellAreaContext *context,
+                                                                    gint                for_width,
+                                                                    gint               *minimum_height,
+                                                                    gint               *natural_height);
 void         gtk_cell_area_context_get_preferred_height             (GtkCellAreaContext *context,
                                                                     gint               *minimum_height,
                                                                     gint               *natural_height);
+void         gtk_cell_area_context_get_preferred_width_for_height   (GtkCellAreaContext *context,
+                                                                    gint                for_height,
+                                                                    gint               *minimum_width,
+                                                                    gint               *natural_width);
 void         gtk_cell_area_context_get_allocation                   (GtkCellAreaContext *context,
                                                                     gint               *width,
                                                                     gint               *height);
@@ -115,9 +139,17 @@ void         gtk_cell_area_context_get_allocation                   (GtkCellArea
 void         gtk_cell_area_context_push_preferred_width             (GtkCellAreaContext *context,
                                                                     gint                minimum_width,
                                                                     gint                natural_width);
+void         gtk_cell_area_context_push_preferred_height_for_width  (GtkCellAreaContext *context,
+                                                                    gint                for_width,
+                                                                    gint                minimum_height,
+                                                                    gint                natural_height);
 void         gtk_cell_area_context_push_preferred_height            (GtkCellAreaContext *context,
                                                                     gint                minimum_height,
                                                                     gint                natural_height);
+void         gtk_cell_area_context_push_preferred_width_for_height  (GtkCellAreaContext *context,
+                                                                    gint                for_height,
+                                                                    gint                minimum_width,
+                                                                    gint                natural_width);
 
 G_END_DECLS